// History.js It!
// v1.0.1 - 30 September, 2012
// https://gist.github.com/854622
(function (window, undefined) {
    // Prepare our Variables
    var History = window.History,
        $ = window.jQuery,
        document = window.document;
    // Check to see if History.js is enabled for our Browser
    if (!History.enabled) {
        return false;
    }
    // Wait for Document
    $(function () {
        // Prepare Variables
        var
        /* Application Specific Variables */
        contentSelector = '#main,article:first,.article:first,.post:first',
            $content = $(contentSelector).filter(':first'),
            contentNode = $content.get(0),
            $menu = $('#menu,#nav,nav:first,.nav:first').filter(':first'),
            activeClass = 'active selected current youarehere',
            activeSelector = '.active,.selected,.current,.youarehere',
            menuChildrenSelector = '> li,> ul > li',
            completedEventName = 'statechangecomplete',
            /* Application Generic Variables */
            $window = $(window),
            $body = $(document.body),
            rootUrl = History.getRootUrl(),
            scrollOptions = {
                duration: 800,
                easing: 'swing'
            };
        // Ensure Content
        if ($content.length === 0) {
            $content = $body;
        }
        // Internal Helper
        $.expr[':'].internal = function (obj, index, meta, stack) {
            // Prepare
            var $this = $(obj),
                url = $this.attr('href') || '',
                isInternalLink;
            // Check link
            isInternalLink = url.substring(0, rootUrl.length) === rootUrl || url.indexOf(':') === -1;
            // Ignore or Keep
            return isInternalLink;
        };
        // HTML Helper
        var documentHtml = function (html) {
            // Prepare
            var result = String(html).replace(/<\!DOCTYPE[^>]*>/i, '').replace(/<(html|head|body|title|meta|script)([\s\>])/gi, '<div class="document-$1"$2').replace(/<\/(html|head|body|title|meta|script)\>/gi, '</div>');
            // Return
            return result;
        };
        // Ajaxify Helper
        $.fn.ajaxify = function () {
            // Prepare
            var $this = $(this);
            // Ajaxify
            $this.find('a:internal:not(.no-ajaxy)').click(function (event) {
                // Prepare
                var $this = $(this),
                    url = $this.attr('href'),
                    title = $this.attr('title') || null;
                // Continue as normal for cmd clicks etc
                if (event.which == 2 || event.metaKey) {
                    return true;
                }
                // Ajaxify this link
                History.pushState(null, title, url);
                event.preventDefault();
                return false;
            });
            // Chain
            return $this;
        };
        // Ajaxify our Internal Links
        $body.ajaxify();
        // Hook into State Changes
        $window.bind('statechange', function () {
            // Prepare Variables
            var State = History.getState(),
                url = State.url,
                relativeUrl = url.replace(rootUrl, '');
            // Set Loading
            $body.addClass('loading');
            // Start Fade Out
            // Animating to opacity to 0 still keeps the element's height intact
            // Which prevents that annoying pop bang issue when loading in new content
            $content.animate({
                opacity: 0
            }, 800);
            // Ajax Request the Traditional Page
            $.ajax({
                url: url,
                success: function (data, textStatus, jqXHR) {
                    // Prepare
                    var $data = $(documentHtml(data)),
                        $dataBody = $data.find('.document-body:first'),
                        $dataContent = $dataBody.find(contentSelector).filter(':first'),
                        $menuChildren, contentHtml, $scripts;
                    // Fetch the scripts
                    $scripts = $dataContent.find('.document-script');
                    if ($scripts.length) {
                        $scripts.detach();
                    }
                    // Fetch the content
                    contentHtml = $dataContent.html() || $data.html();
                    if (!contentHtml) {
                        document.location.href = url;
                        return false;
                    }
                    // Update the menu
                    $menuChildren = $menu.find(menuChildrenSelector);
                    $menuChildren.filter(activeSelector).removeClass(activeClass);
                    $menuChildren = $menuChildren.has('a[href^="' + relativeUrl + '"],a[href^="/' + relativeUrl + '"],a[href^="' + url + '"]');
                    if ($menuChildren.length === 1) {
                        $menuChildren.addClass(activeClass);
                    }
                    // Update the content
                    $content.stop(true, true);
                    $content.html(contentHtml).ajaxify().css('opacity', 100).show(); /* you could fade in here if you'd like */
                    // Update the title
                    document.title = $data.find('.document-title:first').text();
                    try {
                        document.getElementsByTagName('title')[0].innerHTML = document.title.replace('<', '&lt;').replace('>', '&gt;').replace(' & ', ' &amp; ');
                    } catch (Exception) {}
                    // Add the scripts
                    $scripts.each(function () {
                        var $script = $(this),
                            scriptText = $script.text(),
                            scriptNode = document.createElement('script');
                        scriptNode.appendChild(document.createTextNode(scriptText));
                        contentNode.appendChild(scriptNode);
                    });
                    commentShown = false;
                    if ($('.comment-form').length == 0) commentShown = true;
                    else {
                        // Comment iFrame
                        var jsO, target;
                        jsO = document.createElement("script");
                        jsO.type = "text/javascript";
                        jsO.src = 'http://www.blogger.com/static/v1/jsbin/314201885-comment_from_post_iframe.js';
                        target = document.getElementsByClassName('comment-form');
                        for (var i = 0; i < target.length; i++) {
                            target[i].appendChild(jsO);
                        }
                    }
                    // Complete the change
                    if ($body.ScrollTo || false) {
                        $body.ScrollTo(scrollOptions);
                    } /* http://balupton.com/projects/jquery-scrollto */
                    $body.removeClass('loading');
                    $window.trigger(completedEventName);
                    // Inform Google Analytics of the change
                    if (typeof window._gaq !== 'undefined') {
                        window._gaq.push(['_trackPageview', relativeUrl]);
                    }
                    // Inform ReInvigorate of a state change
                    if (typeof window.reinvigorate !== 'undefined' && typeof window.reinvigorate.ajax_track !== 'undefined') {
                        reinvigorate.ajax_track(url);
                        // ^ we use the full url here as that is what reinvigorate supports
                    }
                },
                error: function (jqXHR, textStatus, errorThrown) {
                    document.location.href = url;
                    return false;
                }
            }); // end ajax
        }); // end onStateChange
    }); // end onDomLoad
})(window); // end closure